package com.dragon.connector.imServer.session;

import com.alibaba.fastjson.JSON;
import com.dragon.connector.imServer.session.service.SessionManger;
import com.dragon.protoJo.bean.msg.UserDTO;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;


@Data
@Slf4j
public class LocalSession implements com.dragon.connector.imServer.session.ServerSession {

    public static final AttributeKey<String> KEY_USER_ID = AttributeKey.valueOf("key_user_id");

    public static final AttributeKey<LocalSession> SESSION_KEY = AttributeKey.valueOf("session_key");

    // 群聊自定义key
    public static final AttributeKey<List<String>> GROUP_ID = AttributeKey.valueOf("group_id");

    public static final AttributeKey<String> CHANNEL_NAME =
            AttributeKey.valueOf("CHANNEL_NAME");

    /**
     * 用户实现服务端会话管理的核心
     */
    //通道
    private Channel channel;
    //用户
    private UserDTO user;

    //session唯一标示
    private final String sessionId;

    private ChannelHandlerContext channelHandlerContext;

    //登录状态
    private boolean isLogin = false;

    // session中存储session 变量值属性
    private Map<String,Object> map = new HashMap<>();

    public LocalSession(ChannelHandlerContext ctx){
        this.channelHandlerContext = ctx;
        this.channel = ctx.channel();
        this.sessionId = buildNewSessionId();
    }

    public static LocalSession LocalSession(ChannelHandlerContext ctx){
        Channel channel = ctx.channel();
        return channel.attr(LocalSession.SESSION_KEY).get();
    }

    public static String buildNewSessionId(){
        String uuid = UUID.randomUUID().toString();
        return uuid.replaceAll("-","");
    }

    public String getSessionId(){
        return sessionId;
    }

    /**
     * 和channel 通道实现双向绑定
     * @return
     */
    public LocalSession bind(){
        log.info("localSession 绑定会话" + channel.remoteAddress());
        channel.attr(LocalSession.SESSION_KEY).set(this);
        channel.attr(LocalSession.GROUP_ID).set(user.getGroupIds());
        channel.attr(CHANNEL_NAME).set(JSON.toJSONString(user));
        return this;
    }

    /**
     * 解绑
     * @return
     */
    public LocalSession unbind(){
        isLogin = false;
        SessionManger.inst().removeSession(getSessionId(),getUserId());
        this.close();
        return this;
    }

    public Boolean isValid(){
        return getUser() !=null ? true : false;
    }

    public synchronized void writeAndFlush(Object pkg){
        if(channel.isWritable()){
            channel.writeAndFlush(pkg);
        }else{
            log.debug("通道很忙，消息被暂存了");
        }
    }
    // 关闭连接

    public synchronized void close(){
        // 用户下线了
        ChannelFuture future = channel.close();
    }

    public UserDTO getUser(){
        return user;
    }

    public void setUser(UserDTO user){
        this.user = user;
        user.setSessionId(this.sessionId);
    }

    public String getUserId(){
        return user.getUserId();
    }

    //反向导航
    public static LocalSession getSession(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        return channel.attr(LocalSession.SESSION_KEY).get();
    }

    public synchronized <T> T get(String key){
        return (T) map.get(key);
    }

    //写Protobuf数据帧
    public synchronized void writeAndClose(Object pkg) {
        channel.writeAndFlush(pkg);
        close();
    }
}
